;
var UCD = UCD || {Core:jQuery};
(function(ucd)
{
	var settings = 
	{
	    svg: "http://www.w3.org/2000/svg",
	    xhtml: "http://www.w3.org/1999/xhtml",
	    xlink: "http://www.w3.org/1999/xlink",
	    xml: "http://www.w3.org/XML/1998/namespace",
	    xmlns: "http://www.w3.org/2000/xmlns/"
	};
	var tool = new MyTool();
	var root = null;

	function MyD3()
	{
		this.children = null;	//儿子，myD3对象
		this.owner = null;  	//svg对象
		this.parent = null;	//父亲，myD3对象
		this.parentChildID = null;	//父亲中的索引
	}

	var proto = MyD3.prototype;
	proto.tool = tool;

	proto.attr = 
	function attr(attribute , value)
	{
		if (!value);
		else if (typeof value == 'function')
		{
			var filter = false;		//为真才会进行相关的设置
			if(filter = value(this))
			{
				this.owner.setAttribute(attribute, filter);
			}
		}
		else
		{
			this.owner.setAttribute(attribute, value);
			this[attribute] = value;
		};
		return this;
	}

	proto.attrAllChildren =
	function attrAllChildren(attribute , value)		//孩子节点批量添加属性
	{
		for(var i = 0; _this = this.children[i]; i++)
		{
			if (!value);
			else if (typeof value == 'function')
			{
				var filter = false;		//为真才会进行相关的设置
				if(filter = value(_this))
				{
					_this.owner.setAttribute(attribute, filter);
				}
			}
			else
			{
				_this.owner.setAttribute(attribute, value);
				_this[attribute] = value;
			};
		}
		return this;
	}

	proto.append =
	function append(name , xml) 
	{
		var setting = xml ? settings.xhtml : settings.svg;
		this.children = this.children || [];
		name = document.createElementNS(setting, name);
		// console.log(this);
		this.owner.appendChild(name);
	 	var child = new MyD3().container(name);
	 	child.parentChildID = this.children.length;
	 	this.children.push(child);
	 	child.parent = this;
	 	return child;
	}

	proto._appendText = 		//使用时需要修正
	function appendText(str)
	{
		var left = this.owner.offsetLeft;
		var top = this.owner.offsetTop;
		var rs = root.append('span', true).text(str).style('display: inline-block; width: 40px; position:absolute;word-break: break-all;left:' + left + 'px;top:' + top +'px;');

		return rs;
	}

	proto.container =
	function container(container) 	//container为DOM元素
	{
		// alert(container);
		if(container) 
		{ 
			this.owner = container;
			this.owner.d3 = this;
			root ? 0 : root = this;
			return this;
		} 
		console.error('myD3 container error');
	}

	proto.filter =
	function filter(func)
	{
		var filterRs = new MyD3();
		filterRs.children = [];
		var child;
		var children = this.children;
		// console.log(typeof func == 'function");
		if(typeof func == 'function')
		{
			for(var i = 0; i < children.length; i++)
			{
				if(  func( child = children[i] ) )
				{
					filterRs.children.push(child);
				}
			}
			// console.log(filterRs);
			return filterRs;
		}
	}

	// proto.text =
	// function text(str)
	// {
	// 	this.owner.textContent = str;
	// 	return this;
	// }

	proto.ancestors =
	function ancestors()
	{
		var ancestorsRs = new MyD3();
		var tmpNode = this;
		while( (tmpNode = tmpNode.parent) )
		{
			ancestorsRs.children.push(tmpNode);
			if(tmpNode.owner.localName == 'svg')	break;
		}
		return ancestorsRs;
	}

	proto.style = 
	function style(str)
	{
		this.owner.style.cssText = str;
		return this;
	}

	proto.css =
	function css(attr, value)
	{
		this.owner.style[attr] = value;
		return this;
	}

	proto.clear = 
	function clear()
	{
		if(this.parent)
		{
			var array = this.parent.children;

			array.splice(this.parentChildID, 1);

			var length = array.length;

			for(var i = this.parentChildID; i < length; i++)
			{
				array[i].parentChildID = i;
			}
		}
		this.owner.d3 = null;
		this.owner = null;
		this.parent = null;
		this.children = null;
		this.parentChildID = null;
	}

	proto.__drag =
	function __drag(target, fn)	//target为绑定的目标对象,fn为回调. 使用使用时自行定制
	{
		var container = target;
		var _this = this;
		var tmp;	
		var node;
		var x;
		var y;

		container.addEventListener('mousedown', function(e)
		{
			if(e.target == _this.owner)
			{
				node = e.target;
				container.addEventListener('mousemove',tmp = function(e){
					x = node.x + e.movementX;
					y = node.y + e.movementY;
			                	node.x = x;
			                	node.y = y;	    
			   	 });
				event.preventDefault();		//要把默认事件屏蔽，不然会出现禁止符号
			}
		});

		container.addEventListener('mouseup',  function(e)
		{
			if(node)
			{
				container.removeEventListener('mousemove',tmp);
			}
			node = null;	//挂载在window上，不会自己重置
		});

		container.addEventListener('mouseleave',  function(e)
		{
			if(node)
			{
				container.removeEventListener('mousemove',tmp);
			}
			node = null;	//挂载在window上，不会自己重置
		});
	}

	//var node = {x:100, y:100, parent: nodeParent, width:40, height:40, curWidth:40, curHeight:40, curX:100, curY:100, zoomWidth:1000, zoomHeight:1000}
	proto.zoom =
	function zoom()	//对节点进行放大然后将视窗移动到固定位置
	{
		var node = this;
		var root = node.parent;
		var domainX = node.x;
		var domainY = node.y;
		var duration = 1400;
		var tickTime = 12;

		if(root.progress && !node.timerId)
		{
		 	return;
		}

		root.progress = true;

		if(node.hasZoomed)
		{
			node.incrementWidth = (node.curWidth - node.width) / duration * tickTime;
			node.incrementHeight = (node.curHeight - node.height) / duration * tickTime;
			node.incrementX = (node.curX - node.x) / duration * tickTime;
			node.incrementY = (node.curY - node.y) / duration * tickTime

		 	node.hasZoomed = false;	//缩小
			node.animationOptions = 
			{
				duration: duration,
				onProgress: function(percent) 
				{
					node.attr('transform', function(d) 		
					{				        
					        	d.curX -= d.incrementX;		
					        	d.curY -= d.incrementY;

					        	// console.log('x:'+ d.curX + "	y:"+d.curY);
						 return 'translate(' + d.curX + ' ' + d.curY + ' )';
					}).attr('width', function(d)
					{
						d.curWidth -= d.incrementWidth;
						return d.curWidth ;
					}).attr('height', function(d)
					{
						d.curHeight -= d.incrementHeight;
						d.text.attr('x', d.curX + d.curWidth / 2).attr('y', d.curY + d.curHeight / 2);
						return d.curHeight ;
					});
				}, 
				onComplete: function(percent) 
				{		//结束时函数，这里要做统一的初始化，不然由于时刻划分问题会有细微的差距
					node.attr('transform', function(d) 		//对子节点进行操作
					{  		
						     	// console.log(d.x + ' ' + d.y);

							d.curX = d.x;
							d.curY =  d.y;
							// console.log("x:"+ d.x + "	y:"+d.y);
							return 'translate(' + d.curX + ' ' + d.curY + ' )';
							// return "translate("+ d.curX + ' ' + d.curY +' )';
					}).attr('width', function(d)
					{
							d.curWidth =  d.width;
							return d.curWidth;
					}).attr('height', function(d)
					{
						d.curHeight = d.height;
						d.text.attr('x', d.curX + d.curWidth / 2).attr('y', d.curY + d.curHeight / 2);
						return d.curHeight;
					});
					node.timerId = null;
					root.progress = false;
				}
			};
		}
		else
		{
			node.incrementWidth = (node.zoomWidth - node.curWidth) / duration * tickTime;
			node.incrementHeight = (node.zoomHeight - node.curHeight) / duration * tickTime;
			node.incrementX = (node.zoomX - node.curX) / duration * tickTime;
			node.incrementY = (node.zoomY - node.curY) / duration * tickTime;

			node.hasZoomed = true;
			node.animationOptions = 
			{
			duration: duration,
			      onProgress: function(percent) 
			      {
				      node.attr('transform', function(d) 		
				      {				        
			        		d.curX += d.incrementX;		
			        		d.curY += d.incrementY;
			        		// console.log("x:"+ d.curX + "	y:"+d.curY);
				        	return 'translate(' + d.curX + ' ' + d.curY + ' )';
				       }).attr('width', function(d)
				       {
				       	d.curWidth += d.incrementWidth;
				       	return d.curWidth ;
				       }).attr('height', function(d)
				       {
				       	d.curHeight += d.incrementHeight;
				       	d.text.attr('x', d.curX + d.curWidth / 2).attr('y', d.curY + d.curHeight / 2);
				       	return d.curHeight ;
				       });

				      // console.log(parent);
				      // console.log("end\n");
			        		
			      }, 
			      onComplete: function(percent) 
			      {		//结束时函数，这里要做统一的初始化，不然由于时刻划分问题会有细微的差距
					node.attr('transform', function(d) 		//对子节点进行操作
					{  		
					     	// console.log(d.x + ' ' + d.y);

						d.curX = d.zoomX ;
						d.curY =  d.zoomY;
						// console.log("x:"+ d.x + "	y:"+d.y);
						return 'translate(' + d.curX + ' ' + d.curY + ' )';
						// return "translate("+ d.curX + ' ' + d.curY +' )';
					}).attr('width', function(d)
					{
						d.curWidth =  d.zoomWidth;
						return d.curWidth;
					}).attr('height', function(d)
					{
						d.curHeight = d.zoomHeight;
						d.text.attr('x', d.curX + d.curWidth / 2).attr('y', d.curY + d.curHeight / 2);
						return d.curHeight;
					});

					node.timerId = null;
					root.progress = false;
			      }
			};

		}

		if( root.progress && node.timerId)
		{
		 	clearInterval(node.timerId);
		}

	   	node.timerId = node.tool.animate(node.animationOptions);   //设置动画时间间隔，并调用onProgress等函数进行重绘

		return this;
	}

	//var node = {fadeFrom: 1, fadeTo: 0.5}
	proto.fade =
	function fade()		//淡入淡出
	{
		var node = this;
		var duration = node.duration || 600;
		var tickTime = 12;
		var fadeTo = node.fadeTo || 0;
		var fadeFrom = node.fadeFrom || 1;

		if(node.hasFaded)
		{
		 	node.hasFaded = false;	//淡出
			node.animationOptions = 
			{
			duration: duration,
			onProgress: function(percent) 
			{
				node.attr('opacity', fadeTo + (fadeFrom - fadeTo) * percent);
			}, 
			      onComplete: function(percent) 
			      {		//结束时函数，这里要做统一的初始化，不然由于时刻划分问题会有细微的差距
				node.attr('opacity', fadeFrom);
				node.timerId = null;
			      }
			};
		}
		else
		{
			node.hasFaded = true;	//淡入
			node.animationOptions = 
			{
			      duration: duration,
			      onProgress: function(percent) 
			      {
				node.attr('opacity', (1 - percent) * (fadeFrom - fadeTo ) + fadeTo);
				      // console.log(parent);
				      // console.log('end\n');
			        		
			      }, 
			      onComplete: function(percent) 
			      {		//结束时函数，这里要做统一的初始化，不然由于时刻划分问题会有细微的差距
				node.attr('opacity', fadeTo);
				node.timerId = null;
			      }
			};

		}

		if(node.timerId)
		{
		 	clearInterval(node.timerId);
		}

	   	node.timerId = node.tool.animate(node.animationOptions);   //设置动画时间间隔，并调用onProgress等函数进行重绘

		return this;
	}

	proto.marginTop =
	function marginTop()		//撑开缩回,配合CSS可以实现上下滑动
	{
		var node = this;
		var style = node.owner.style;
		var duration = node.duration || 200;
		var tickTime = 12;
		var marginTopTo = node.marginTopTo || 0;
		var marginTopFrom = node.marginTopFrom || 0;

		if(node.progress)	return;

		node.progress = true;

		if(node.hasMarginTop)
		{
		 	node.hasMarginTop = false;	
			node.animationOptions = 
			{
			duration: duration,
			onProgress: function(percent) 
			{
				style.marginTop = marginTopTo + (marginTopFrom - marginTopTo) * percent;
			}, 
			      onComplete: function(percent) 
			      {		//结束时函数，这里要做统一的初始化，不然由于时刻划分问题会有细微的差距
				style.marginTop = marginTopFrom;
				node.timerId = null;
				node.progress = false;
			      }
			};
		}
		else
		{
			node.hasMarginTop = true;	
			node.animationOptions = 
			{
			      duration: duration,
			      onProgress: function(percent) 
			      {
				style.marginTop = (1 - percent) * (marginTopFrom - marginTopTo ) + marginTopTo;
				      // console.log(parent);
				      // console.log('end\n');
			        		
			      }, 
			      onComplete: function(percent) 
			      {		//结束时函数，这里要做统一的初始化，不然由于时刻划分问题会有细微的差距
				style.marginTop = marginTopTo;
				node.timerId = null;
				node.progress = false;
			      }
			};

		}

		if(node.timerId)
		{
		 	clearInterval(node.timerId);
		}

	   	node.timerId = node.tool.animate(node.animationOptions);   //设置动画时间间隔，并调用onProgress等函数进行重绘

		return this;
	}

	proto.arcAppend =
	function arcAppend(node)		// var node = {name:'YY', color:'black', value:0.3, r: 80};		按百分比添加一段弧
	{
		var r = node.r;
		var x = 100;	//圆心
		var y = 100;
		var padding = 1; //间隔
		var value = node.value < 1 ? node.value : 0.99999;
		var largeArcFlag = value > 0.5 ? 1 : 0;
		var endDeg = startDeg + tool.deg2rad(360 * value - padding);
		var startX = Math.sin(startDeg) * r + x;
		var startY = - Math.cos(startDeg) * r + y;
		var endX = Math.sin(endDeg) * r + x;
		var endY = - Math.cos(endDeg) * r + y;
		var arc = this.svg.append('path').attr('d', 'M' + startX + ',' + startY + ' A ' + r + ',' + r + ' 0 ' + largeArcFlag + ' 1 ' + endX + ',' + endY)		//(x-x1)^2 + (y-y1)^2 = r^2 椭圆、圆公式
				.attr('fill', 'none')
				.attr('stroke', tool.color())
				.attr('stroke-width', strokeWidth);
		node.arc = arc;
		arc.node = node;
		node.startDeg = startDeg;
		startDeg = endDeg + tool.deg2rad(padding); 
	}
//________________________________________________________________________________________________
	function MyTool()
	{
		var COLOR = ['#fe4365','#fc9c99','#f9d9ad','#d4d4a9','#83af9b','rgb(86, 135, 209)','rgb(222, 120, 59)','rgb(106, 185, 117)','rgb(161, 115, 209)','rgb(187, 187, 187)','#999'];
		var counter = 0;
		
		this.animate = animate;
		this.color = color;
		this.deg2rad = deg2rad;
		this.rad2deg = rad2deg;
		this.jsonAttrParent = jsonAttrParent;		//深度遍历，递归
		this.jsonAttrParentB = jsonAttrParentB;	//广度遍历，非递归
		this.timeCaculate = timeCaculate;
		this.randomArray = randomArray;
		this.sleep = sleep;
		this.myTimer = myTimer;
		this.round = round;
		this.mul = mul;		

		function color()
		{
			return COLOR[(counter++) % COLOR.length];
		}

		function deg2rad(deg) 
		{
			return deg * Math.PI / 180;
		}

		function rad2deg(rad) 
		{
			return rad * 180 / Math.PI;
		}

		function myTimer(fn, ms, args)	//带参数的
		{
			if(args)
			{
				return setInterval(function(args2){ return function() { fn(args2)}}(args), ms);

			}else
			{
				return setInterval(fn, ms);
			}
		}

		//var json{ children:[]}
		function jsonAttrParent(json)		//深度遍历,json子节点加parent属性
		{
			var length = json.children.length;

			for(var i = 0; i < length; i++)
			{
				json.children[i].parent = json;
				this.jsonAttrParent(json.children[i]);
			}
		}

		//var json{ children:[]}
		function jsonAttrParentB(json)			//广度遍历
		{
			var curNode;
			var nodes = json.children;
			var childrenNodes = [];
			var cur = 0;
			var length = nodes.length;
			var childrenLength;

			while(length)		//广度遍历
			{
				cur = 0;
				while(cur < length)
				{
					curNode = nodes[cur++];
					childrenLength = curNode.children ? curNode.children.length : 0;
					for(var i =0; i < childrenLength; i++)
					{
						childrenNodes.push(curNode.children[i]);
						curNode.children[i].parent = curNode;
					}
				}

				nodes = childrenNodes;
				childrenNodes = [];
			}
		}

		function timeCaculate(time, add)	//var time ={hour:1, min:1, s:1}，add为加的秒钟
		{
			time.s += add;
			time.s = Math.round(time.s);
			while(time.s >= 60)
			{
				time.min += 1;
				time.s -= 60;
			}
			
			while(time.min >= 60)
			{
				time.hour += 1;
				time.min -= 60;
			}

			while(time.hour >= 24)
			{
				time.hour -= 24;
			}

			var textHour;
			var textMin;
			var textS;

			textHour = time.hour < 10 ? '0' + time.hour : time.hour;
			textMin = time.min < 10 ? '0' + time.min : time.min;
			textS = time.s < 10 ? '0' + time.s : time.s;

			return textHour + ':' +textMin+ ':' +textS;
		}
		
		function round(num, accurate)
		{
			var k = Math.pow(10, accurate);
			return Math.round(num * k) / k;
		}

		function randomArray(num, range, accurate)		//num个数， range最大值， accurate精确到几位小数（不设置不省略）
		{
			var rs = [];
			var random = Math.random;
			var round = Math.round;
			var k = 1;
			if(accurate >= 0)
			{
				k = Math.pow(10, accurate);
			
				for(var i = 0; i < num; i++)
				{
					rs[i] = round(random() * range * k) / k;
				}
			}else
			{
				for(var i = 0; i < num; i++)
				{
					rs[i] = random() * range;
				}	
			}

			return rs;
		}

		function sleep(ms)		// ms 毫秒
		{
			  for(var t = Date.now();Date.now() - t <= ms;);
		}

		/*
		var options =
		{
			duration: 1000,
			startTime : 0,
			onProgress: function() 	
			{
			
			}, 
			onComplete: function(percent) 
			{		//结束时函数，这里要做统一的初始化，不然由于时刻划分问题会有细微的差距

			}
		};
		*/
		function animate(options)
		{
			var opts = options;
			var tickTime = 12;
			var timerId;
			var duration = opts.duration || 500; 
			var startTime = opts.startTime || 0;
			var endTime = startTime + duration;
			var curTime = 0;

			var tick = function() 
			{
				curTime += tickTime;
				remain = endTime - curTime;
				percent = 1 - remain / duration;
				if (percent >= 1) 
				{
					clearInterval(timerId);
					timerId = null;
					typeof opts.onComplete == 'function' && opts.onComplete(percent);
				} else 
				{
					typeof opts.onProgress == 'function' && opts.onProgress(percent);
				}
			};
			return timerId = setInterval(tick, tickTime);
		}

		function mul(arg1, arg2)
		{
			var s1 = arg1.toString();
			var s2 = arg2.toString();
			var l1 = s1.split(".")[1];
			var l2 = s2.split(".")[1];
			l1 ? l1 = l1.length : l1 = 0;
			l2 ? l2 = l2.length : l2 = 0;
			return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, l1 + l2);
		}

	}

//________________________________________________________________________________________________
	// MyD3.prototype = document.createElementNS.prototype;
	// MyD3.constructor = MyD3;
	ucd.MyD3 = MyD3;
})(UCD);